package com.liuhuanss.voiceprint.service;

import com.liuhuanss.voiceprint.config.VoiceprintProperties;
import com.liuhuanss.voiceprint.entity.User;
import com.liuhuanss.voiceprint.util.AudioUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * 认证服务类
 * 
 * @author liuhuanss
 * @version 1.0
 */
@Service
@Slf4j
public class AuthService {
    
    private static final String VOICEPRINT_GROUP_ID = "voiceprint_login_group";

    @Autowired
    private UserService userService;

    @Autowired
    private VoiceprintService voiceprintService;

    @Autowired
    private AudioUtil audioUtil;

    @Autowired
    private VoiceprintProperties voiceprintProperties;

    /**
     * 声纹登录（使用MultipartFile）
     * 
     * @param username 用户名
     * @param audioFile 音频文件
     * @return 登录结果
     */
    public Map<String, Object> voiceprintLogin(String username, MultipartFile audioFile) {
        try {
            // 转换音频文件为Base64
            String audioBase64 = audioUtil.multipartFileToBase64(audioFile);
            return voiceprintLogin(username, audioBase64);
        } catch (Exception e) {
            log.error("声纹登录失败（文件处理错误）", e);
            throw new RuntimeException("音频文件处理失败: " + e.getMessage());
        }
    }

    /**
     * 声纹登录（使用Base64数据）
     * 
     * @param username 用户名
     * @param audioBase64 音频Base64数据
     * @return 登录结果
     */
    public Map<String, Object> voiceprintLogin(String username, String audioBase64) {
        log.info("开始声纹登录验证，用户名: {}", username);
        
        try {
            // 去掉可能的 data URL 前缀
            audioBase64 = audioUtil.stripDataUrlPrefix(audioBase64);

            // 1. 查找用户
            User user = userService.findByUsername(username);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            // 2. 检查用户是否启用声纹识别
            if (user.getIsVoiceprintEnabled()==0) {
                throw new RuntimeException("该用户未启用声纹识别功能");
            }
            
            // 3. 检查用户是否有声纹特征ID
            if (user.getVoiceprintFeatureId() == null || user.getVoiceprintFeatureId().trim().isEmpty()) {
                throw new RuntimeException("用户声纹特征未注册");
            }
            
            // 4. 进行1:1声纹比对
            Map<String, Object> compareResult = voiceprintService.searchOneFeature(
                VOICEPRINT_GROUP_ID, 
                user.getVoiceprintFeatureId(), 
                audioBase64
            );
            
            // 5. 解析比对结果
            boolean isMatch = parseVoiceprintResult(compareResult);
            
            if (!isMatch) {
                throw new RuntimeException("声纹验证失败，请重新录制音频");
            }
            
            // 6. 更新用户最后登录时间
            user.setUpdatedAt(LocalDateTime.now());
            userService.save(user);
            
            // 7. 构建登录成功响应
            Map<String, Object> result = new HashMap<>();
            result.put("userId", user.getId());
            result.put("username", user.getUsername());
            result.put("voiceprintEnabled", user.getIsVoiceprintEnabled());
            result.put("voiceprintFeatureId", user.getVoiceprintFeatureId());
            result.put("loginTime", LocalDateTime.now());
            result.put("voiceprintResult", compareResult);
            
            log.info("声纹登录验证成功，用户: {}", username);
            return result;
        } catch (Exception e) {
            log.error("声纹登录失败，用户: {}", username, e);
            throw new RuntimeException("声纹登录失败: " + e.getMessage());
        }
    }

    /**
     * 注册声纹特征（使用MultipartFile）
     * 
     * @param username 用户名
     * @param audioFile 音频文件
     * @return 注册结果
     */
    public Map<String, Object> registerVoiceprint(String username, MultipartFile audioFile) {
        try {
            // 转换音频文件为Base64
            String audioBase64 = audioUtil.multipartFileToBase64(audioFile);
            return registerVoiceprint(username, audioBase64);
        } catch (Exception e) {
            log.error("注册声纹特征失败（文件处理错误）", e);
            throw new RuntimeException("音频文件处理失败: " + e.getMessage());
        }
    }

    /**
     * 注册声纹特征（使用Base64数据）
     * 
     * @param username 用户名
     * @param audioBase64 音频Base64数据
     * @return 注册结果
     */
    public Map<String, Object> registerVoiceprint(String username, String audioBase64) {
        log.info("开始注册声纹特征，用户名: {}", username);
        
        try {
            // 去掉可能的 data URL 前缀
            audioBase64 = audioUtil.stripDataUrlPrefix(audioBase64);

            // 1. 查找用户
            User user = userService.findByUsername(username);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            // 2. 检查用户是否已经注册过声纹
//            if (user.getIsVoiceprintEnabled() &&
//                user.getVoiceprintFeatureId() != null &&
//                !user.getVoiceprintFeatureId().trim().isEmpty()) {
//                throw new RuntimeException("用户已注册声纹特征，请先删除现有特征");
//            }
            
            // 3. 确保声纹特征库存在
            try {
                voiceprintService.createFeatureGroup(VOICEPRINT_GROUP_ID);
            } catch (Exception e) {
                // 如果特征库已存在，忽略错误
                log.debug("声纹特征库可能已存在: {}", e.getMessage());
            }
            
            // 4. 生成特征ID
            String featureId = "user_" + user.getId() + "_" + System.currentTimeMillis();
            log.info("开始生成特征ID: {}", featureId);
            // 5. 添加声纹特征
            log.info("开始添加声纹特征，特征ID: {}", featureId);
            Map<String, Object> addResult = voiceprintService.addAudioFeature(
                VOICEPRINT_GROUP_ID, 
                featureId, 
                "用户 " + username + " 的声纹特征", 
                audioBase64
            );
            log.info("声纹特征添加成功，结果: {}", addResult);
            // 6. 检查添加结果
            if (!isVoiceprintOperationSuccess(addResult)) {
                throw new RuntimeException("声纹特征添加失败");
            }
            
            // 7. 更新用户信息
            user.setIsVoiceprintEnabled(1);
            user.setVoiceprintFeatureId(featureId);
            user.setUpdatedAt(LocalDateTime.now());
            userService.save(user);
            
            // 8. 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("userId", user.getId());
            result.put("username", user.getUsername());
            result.put("voiceprintEnabled", user.getIsVoiceprintEnabled());
            result.put("voiceprintFeatureId", user.getVoiceprintFeatureId());
            result.put("registrationTime", LocalDateTime.now());
            result.put("voiceprintResult", addResult);
            
            log.info("声纹特征注册成功，用户: {}, 特征ID: {}", username, featureId);
            return result;
            
        } catch (Exception e) {
            log.error("注册声纹特征失败，用户: {}", username, e);
            throw new RuntimeException("注册声纹特征失败: " + e.getMessage());
        }
    }

    /**
     * 获取当前用户信息（通过JWT令牌）
     * 
     * @param token JWT令牌
     * @return 用户信息
     */
    public User getCurrentUser(String token) {
        try {
            // 解析token获取用户ID（简化版本）
            Long userId = parseTokenToUserId(token);
            
            User user = userService.findById(userId);
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            return user;
        } catch (Exception e) {
            log.error("获取当前用户信息失败", e);
            throw new RuntimeException("获取用户信息失败: " + e.getMessage());
        }
    }

    /**
     * 用户登出
     * 
     * @param token JWT令牌
     */
    public void logout(String token) {
        try {
            // 在实际项目中，这里应该将token加入黑名单
            log.info("用户登出，token: {}", token.substring(0, Math.min(token.length(), 20)) + "...");
        } catch (Exception e) {
            log.error("用户登出失败", e);
            throw new RuntimeException("登出失败: " + e.getMessage());
        }
    }

    /**
     * 解析声纹比对结果
     * 
     * @param result 声纹服务返回的结果
     * @return 是否匹配
     */
    private boolean parseVoiceprintResult(Map<String, Object> result) {
        try {
            // 检查响应状态
            Integer code = (Integer) result.get("code");
            if (code == null || code != 0) {
                log.warn("声纹比对API返回错误: {}", result.get("message"));
                return false;
            }
            
            // 获取数据部分
            @SuppressWarnings("unchecked")
            Map<String, Object> data = (Map<String, Object>) result.get("data");
            if (data == null) {
                log.warn("声纹比对结果数据为空");
                return false;
            }
            
            // 获取相似度分数
            Object scoreObj = data.get("score");
            if (scoreObj == null) {
                log.warn("声纹比对结果中没有相似度分数");
                return false;
            }
            
            double score;
            if (scoreObj instanceof Number) {
                score = ((Number) scoreObj).doubleValue();
            } else {
                score = Double.parseDouble(scoreObj.toString());
            }
            
            double threshold = voiceprintProperties.getRecognition().getSimilarityThreshold();
             log.info("声纹比对相似度: {}, 阈值: {}", score, threshold);
             return score >= threshold;
            
        } catch (Exception e) {
            log.error("解析声纹比对结果失败", e);
            return false;
        }
    }

    /**
     * 检查声纹操作是否成功
     * 
     * @param result 操作结果
     * @return 是否成功
     */
    private boolean isVoiceprintOperationSuccess(Map<String, Object> result) {
        try {
            Integer code = (Integer) result.get("code");
            return code != null && code == 0;
        } catch (Exception e) {
            log.error("检查声纹操作结果失败", e);
            return false;
        }
    }

    /**
     * 生成JWT Token（简化版本）
     * 
     * @param user 用户
     * @return token
     */
    private String generateToken(User user) {
        // 这里是简化版本，实际应该使用JWT库
        return "voiceprint_token_" + user.getId() + "_" + System.currentTimeMillis();
    }

    /**
     * 解析Token获取用户ID（简化版本）
     * 
     * @param token JWT令牌
     * @return 用户ID
     */
    private Long parseTokenToUserId(String token) {
        try {
            // 简化版本的token解析
            if (token.startsWith("voiceprint_token_")) {
                String[] parts = token.split("_");
                if (parts.length >= 3) {
                    return Long.parseLong(parts[2]);
                }
            }
            throw new RuntimeException("无效的token格式");
        } catch (Exception e) {
            throw new RuntimeException("token解析失败: " + e.getMessage());
        }
    }
}